package com.example.wechat.login.aspect;

import com.example.wechat.login.annotation.Idempotent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 幂等性切面
 */
@Aspect
@Component
public class IdempotentAspect {

    @Resource
    private RedissonClient redissonClient;

    @Around("@annotation(idempotent)")
    public Object around(ProceedingJoinPoint joinPoint, Idempotent idempotent) throws Throwable {
        // 获取用户 ID
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        String userId = (String) authentication.getPrincipal();

        // 构建幂等性键
        String key = idempotent.keyPrefix() + userId;

        // 检查是否可以访问
        RBucket<Long> bucket = redissonClient.getBucket(key);
        long currentTime = System.currentTimeMillis();
        if (bucket.get() == null) {
            bucket.set(currentTime, idempotent.expireTime(), TimeUnit.MILLISECONDS);
            return joinPoint.proceed();
        } else {
            long lastAccessTime = bucket.get();
            if (currentTime - lastAccessTime >= idempotent.expireTime()) {
                bucket.set(currentTime, idempotent.expireTime(), TimeUnit.MILLISECONDS);
                return joinPoint.proceed();
            }
            throw new RuntimeException("操作过于频繁，请稍后再试");
        }
    }
}